package com.sc.nft.admin.consume;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.sc.nft.admin.request.SecondBuyValuationRequest;
import com.sc.nft.dao.AutoUserListDao;
import com.sc.nft.dao.PropLowestPriceDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.entity.AutoUserList;
import com.sc.nft.entity.SecondCollection;
import com.sc.nft.entity.SecondEquityProps;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.vo.GetPaySignVO;
import com.sc.nft.entity.vo.secondEquityProp.SecondEquityPropCreateOrderVO;
import com.sc.nft.enums.MessageTopic;
import com.sc.nft.enums.PayMethodEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.ModelException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.PayOrderService;
import com.sc.nft.service.SecondEquityPropsOrderService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@RocketMQMessageListener(topic = MessageTopic.PROPS_FREE_MARKET + "${spring.profiles.active}", consumerGroup = MessageTopic.PROPS_FREE_MARKET + "${spring.profiles.active}")
@Component
@Slf4j
@RequiredArgsConstructor
public class AutoBuyPropConsumer implements RocketMQListener<SecondEquityProps> {
    private final PropLowestPriceDao propLowestPriceDao;
    private final UserInfoDao userInfoDao;
    private final AutoUserListDao autoUserListDao;
    private final Redisson redisson;
    private final SecondEquityPropsOrderService secondOrderService;
    private final PayOrderService payOrderService;

    @Override
    public void onMessage(SecondEquityProps message) {
        boolean exists = propLowestPriceDao.exists(message.getEquityPropsId(), message.getSalesPrice());
        if (!exists) {
            return;
        }
        SecondBuyValuationRequest secondBuyValuationRequest = new SecondBuyValuationRequest();
        secondBuyValuationRequest.setEquityPropsId(message.getEquityPropsId());
        secondBuyValuationRequest.setSecondProductIds(Lists.newArrayList(message.getId()));
        List<RLock> lock = new ArrayList();
        SecondEquityPropCreateOrderVO vo = null;
        try {
            // 用来存放被锁的id
            List<Long> mallLockId = new ArrayList<>();
            secondBuyValuationRequest.getSecondProductIds().forEach(aLong -> {
                // lock的key组成  LOCK_ORDER挂售id
                String key = StrUtil.format(RedisKeyEnum.LOCK_CONSIGN_EQUITY_PROPS.getKey(), aLong);
                RLock orderLock = redisson.getLock(key);
                log.info("二级锁单Key:{}", key);
                boolean heldByCurrentThread = orderLock.tryLock();
                if (!heldByCurrentThread) {
                    // 把挂载的商品id返回去.
                    mallLockId.add(aLong);
                } else {
                    lock.add(orderLock);
                }
            });
            if (CollUtil.isNotEmpty(mallLockId)) {
                throw new ModelException(mallLockId, ErrorCode.COUNT_NOT_ENOUGH);
            }
            log.info("锁单入参请求参数:{}", JSON.toJSON(secondBuyValuationRequest));
            UserInfo userInfo = userInfoDao.getById(autoUserListDao.getRandomOne().getUserId());
            vo = secondOrderService.createOrder(userInfo, secondBuyValuationRequest.getEquityPropsId(), secondBuyValuationRequest.getSecondProductIds());
            GetPaySignVO paySecond = payOrderService.getPayProps(PayMethodEnum.WALLET_PAY, vo.getOrderIds(),
                    null, userInfo, "127.0.0.1", null, false, null, null);
            payOrderService.verifyPay(userInfo, paySecond.getId(), userInfo.getTransactionPassword(), null, null);
        } catch (Exception e) {
            //就抢一次 留一线生机
            log.warn("没抢到：", e);
        } finally {
            // 批量释放锁
            lock.forEach(rLock -> {
                if (rLock.isLocked()) {
                    rLock.unlock();
                }
                log.info("二级释放Key:{}", rLock);
            });
        }
    }
}
